home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint96sb.zoo / src / unifs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-10  |  11.9 KB  |  569 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* a simple unified file system */
  6.  
  7. #include "mint.h"
  8.  
  9.  
  10. extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
  11.  
  12. static long    ARGS_ON_STACK uni_root    P_((int drv, fcookie *fc));
  13. static long    ARGS_ON_STACK uni_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  14. static long    ARGS_ON_STACK uni_getxattr    P_((fcookie *fc, XATTR *xattr));
  15. static long    ARGS_ON_STACK uni_chattr    P_((fcookie *fc, int attrib));
  16. static long    ARGS_ON_STACK uni_chown    P_((fcookie *fc, int uid, int gid));
  17. static long    ARGS_ON_STACK uni_chmode    P_((fcookie *fc, unsigned mode));
  18. static long    ARGS_ON_STACK uni_rmdir    P_((fcookie *dir, const char *name));
  19. static long    ARGS_ON_STACK uni_remove    P_((fcookie *dir, const char *name));
  20. static long    ARGS_ON_STACK uni_getname    P_((fcookie *root, fcookie *dir, char *pathname));
  21. static long    ARGS_ON_STACK uni_rename    P_((fcookie *olddir, char *oldname,
  22.                     fcookie *newdir, const char *newname));
  23. static long    ARGS_ON_STACK uni_opendir    P_((DIR *dirh, int flags));
  24. static long    ARGS_ON_STACK uni_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  25. static long    ARGS_ON_STACK uni_rewinddir    P_((DIR *dirh));
  26. static long    ARGS_ON_STACK uni_closedir    P_((DIR *dirh));
  27. static long    ARGS_ON_STACK uni_pathconf    P_((fcookie *dir, int which));
  28. static long    ARGS_ON_STACK uni_dfree    P_((fcookie *dir, long *buf));
  29. static DEVDRV *    ARGS_ON_STACK uni_getdev    P_((fcookie *fc, long *devsp));
  30. static long    ARGS_ON_STACK uni_symlink    P_((fcookie *dir, const char *name, const char *to));
  31. static long    ARGS_ON_STACK uni_readlink    P_((fcookie *fc, char *buf, int buflen));
  32.  
  33. FILESYS uni_filesys = {
  34.     (FILESYS *)0,
  35.     0,
  36.     uni_root,
  37.     uni_lookup, nocreat, uni_getdev, uni_getxattr,
  38.     uni_chattr, uni_chown, uni_chmode,
  39.     nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
  40.     uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
  41.     uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
  42.     uni_symlink, uni_readlink, nohardlink, nofscntl, nodskchng
  43. };
  44.  
  45. /*
  46.  * structure that holds files
  47.  * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
  48.  *    "dev" holds the appropriate BIOS device number, and
  49.  *    "data" is meaningless
  50.  * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
  51.  *    "dev" holds the user id of the owner, and
  52.  *    "data" points to the actual link data
  53.  */
  54.  
  55. typedef struct unifile {
  56.     char name[NAME_MAX+1];
  57.     ushort mode;
  58.     ushort dev;
  59.     FILESYS *fs;
  60.     void *data;
  61.     struct unifile *next;
  62. } UNIFILE;
  63.  
  64. static UNIFILE u_drvs[UNI_NUM_DRVS];
  65. static UNIFILE *u_root = 0;
  66.  
  67. void
  68. unifs_init()
  69. {
  70.     UNIFILE *u = u_drvs;
  71.     int i;
  72.  
  73.     u_root = u;
  74.     for (i = 0; i < UNI_NUM_DRVS; i++,u++) {
  75.         u->next = u+1;
  76.         u->mode = S_IFDIR|DEFAULT_DIRMODE;
  77.         u->dev = i;
  78.         if (i == PROCDRV) {
  79.             strcpy(u->name, "proc");
  80.             u->fs = &proc_filesys;
  81.         } else if (i == PIPEDRV) {
  82.             strcpy(u->name, "pipe");
  83.             u->fs = &pipe_filesys;
  84.         } else if (i == BIOSDRV) {
  85.             strcpy(u->name, "dev");
  86.             u->fs = &bios_filesys;
  87.         } else if (i == UNIDRV) {
  88.             (u-1)->next = u->next;    /* skip this drive */
  89.         } else if (i == SHMDRV) {
  90.             strcpy(u->name, "shm");
  91.             u->fs = &shm_filesys;
  92.         } else {
  93.             u->name[0] = i + 'a';
  94.             u->name[1] = 0;
  95.             u->fs = 0;
  96.         }
  97.     }
  98.     --u;    /* oops, we went too far */
  99.     u->next = 0;
  100. }
  101.  
  102. static long ARGS_ON_STACK 
  103. uni_root(drv, fc)
  104.     int drv;
  105.     fcookie *fc;
  106. {
  107.     if (drv == UNIDRV) {
  108.         fc->fs = &uni_filesys;
  109.         fc->dev = drv;
  110.         fc->index = 0L;
  111.         return 0;
  112.     }
  113.     fc->fs = 0;
  114.     return EINTRN;
  115. }
  116.  
  117. static long ARGS_ON_STACK 
  118. uni_lookup(dir, name, fc)
  119.     fcookie *dir;
  120.     const char *name;
  121.     fcookie *fc;
  122. {
  123.     UNIFILE *u;
  124.     long drvs;
  125.     FILESYS *fs;
  126.     extern long dosdrvs;
  127.  
  128.     TRACE(("uni_lookup(%s)", name));
  129.  
  130.     if (dir->index != 0) {
  131.         DEBUG(("uni_lookup: bad directory"));
  132.         return EPTHNF;
  133.     }
  134. /* special case: an empty name in a directory means that directory */
  135. /* so do "." and ".." */
  136.  
  137.     if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
  138.         *fc = *dir;
  139.         return 0;
  140.     }
  141.     drvs = drvmap() | dosdrvs | PSEUDODRVS;
  142. /*
  143.  * OK, check the list of aliases and special directories
  144.  */
  145.     for (u = u_root; u; u = u->next) {
  146.         if (!stricmp(name, u->name)) {
  147.             if ( (u->mode & S_IFMT) == S_IFDIR ) {
  148.                 if (u->dev >= NUM_DRIVES) {
  149.                     fs = u->fs;
  150.                     return (*fs->root)(u->dev,fc);
  151.                 }
  152.                 if ((drvs & (1L << u->dev)) == 0)
  153.                     return EPTHNF;
  154.                 *fc = curproc->root[u->dev];
  155.                 if (!fc->fs) {        /* drive changed? */
  156.                     changedrv(fc->dev);
  157.                     *fc = curproc->root[u->dev];
  158.                     if (!fc->fs)
  159.                         return EPTHNF;
  160.                 }
  161.             } else {        /* a symbolic link */
  162.                 fc->fs = &uni_filesys;
  163.                 fc->dev = UNIDRV;
  164.                 fc->index = (long)u;
  165.             }
  166.             return 0;
  167.         }
  168.     }
  169.     DEBUG(("uni_lookup: name (%s) not found", name));
  170.     return EFILNF;
  171. }
  172.  
  173. static long ARGS_ON_STACK 
  174. uni_getxattr(fc, xattr)
  175.     fcookie *fc;
  176.     XATTR *xattr;
  177. {
  178.     UNIFILE *u = (UNIFILE *)fc->index;
  179.  
  180.     if (fc->fs != &uni_filesys) {
  181.         ALERT("ERROR: wrong file system getxattr called");
  182.         return EINTRN;
  183.     }
  184.  
  185.     xattr->index = fc->index;
  186.     xattr->dev = fc->dev;
  187.     xattr->nlink = 1;
  188.     xattr->blksize = 1;
  189.  
  190. /* If "u" is null, then we have the root directory, otherwise
  191.  * we use the UNIFILE structure to get the info about it
  192.  */
  193.     if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
  194.         xattr->uid = xattr->gid = 0;
  195.         xattr->size = xattr->nblocks = 0;
  196.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  197.         xattr->attr = FA_DIR;
  198.     } else {
  199.         xattr->uid = u->dev;
  200.         xattr->gid = 0;
  201.         xattr->size = xattr->nblocks = strlen(u->data) + 1;
  202.         xattr->mode = u->mode;
  203.         xattr->attr = 0;
  204.     }
  205.     xattr->mtime = xattr->atime = xattr->ctime = 0;
  206.     xattr->mdate = xattr->adate = xattr->cdate = 0;
  207.     return 0;
  208. }
  209.  
  210. static long ARGS_ON_STACK 
  211. uni_chattr(dir, attrib)
  212.     fcookie *dir;
  213.     int attrib;
  214. {
  215.     UNUSED(dir); UNUSED(attrib);
  216.     return EACCDN;
  217. }
  218.  
  219. static long ARGS_ON_STACK 
  220. uni_chown(dir, uid, gid)
  221.     fcookie *dir;
  222.     int uid, gid;
  223. {
  224.     UNUSED(dir); UNUSED(uid);
  225.     UNUSED(gid);
  226.     return EINVFN;
  227. }
  228.  
  229. static long ARGS_ON_STACK 
  230. uni_chmode(dir, mode)
  231.     fcookie *dir;
  232.     unsigned mode;
  233. {
  234.     UNUSED(dir);
  235.     UNUSED(mode);
  236.     return EINVFN;
  237. }
  238.  
  239. static long ARGS_ON_STACK 
  240. uni_rmdir(dir, name)
  241.     fcookie *dir;
  242.     const char *name;
  243. {
  244.     long r;
  245.  
  246.     r = uni_remove(dir, name);
  247.     if (r == EFILNF) r = EPTHNF;
  248.     return r;
  249. }
  250.  
  251. static long ARGS_ON_STACK 
  252. uni_remove(dir, name)
  253.     fcookie *dir;
  254.     const char *name;
  255. {
  256.     UNIFILE *u, *lastu;
  257.  
  258.     UNUSED(dir);
  259.  
  260.     lastu = 0;
  261.     u = u_root;
  262.     while (u) {
  263.         if (!strncmp(u->name, name, NAME_MAX)) {
  264.             if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
  265.             kfree(u->data);
  266.             if (lastu)
  267.                 lastu->next = u->next;
  268.             else
  269.                 u_root = u->next;
  270.             kfree(u);
  271.             return 0;
  272.         }
  273.         lastu = u;
  274.         u = u->next;
  275.     }
  276.     return EFILNF;
  277. }
  278.  
  279. static long ARGS_ON_STACK 
  280. uni_getname(root, dir, pathname)
  281.     fcookie *root, *dir; char *pathname;
  282. {
  283.     FILESYS *fs;
  284.     UNIFILE *u;
  285.     char *n;
  286.     fcookie relto;
  287.  
  288.     UNUSED(root);
  289.  
  290.     fs = dir->fs;
  291.     if (dir->dev == UNIDRV) {
  292.         *pathname = 0;
  293.         return 0;
  294.     }
  295.  
  296.     for (u = u_root; u; u = u->next) {
  297.         if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
  298.             *pathname++ = '\\';
  299.             for (n = u->name; *n; )
  300.                 *pathname++ = *n++;
  301.             break;
  302.         }
  303.     }
  304.  
  305.     if (!u) {
  306.         ALERT("unifs: couldn't match a drive with a directory");
  307.         return EPTHNF;
  308.     }
  309.  
  310.     if (dir->dev >= NUM_DRIVES) {
  311.         if ((*fs->root)(dir->dev, &relto) == 0) {
  312.             return (*fs->getname)(&relto, dir, pathname);
  313.         } else {
  314.             *pathname = 0;
  315.             return EINTRN;
  316.         }
  317.     }
  318.  
  319.     if (curproc->root[dir->dev].fs != fs) {
  320.         ALERT("unifs: drive's file system doesn't match directory's");
  321.         return EINTRN;
  322.     }
  323.  
  324.     return (*fs->getname)(&curproc->root[dir->dev], dir, pathname);
  325. }
  326.  
  327. static long ARGS_ON_STACK 
  328. uni_rename(olddir, oldname, newdir, newname)
  329.     fcookie *olddir;
  330.     char *oldname;
  331.     fcookie *newdir;
  332.     const char *newname;
  333. {
  334.     UNIFILE *u;
  335.     fcookie fc;
  336.     long r;
  337.  
  338.     UNUSED(olddir);
  339.  
  340.     for (u = u_root; u; u = u->next) {
  341.         if (!stricmp(u->name, oldname))
  342.             break;
  343.     }
  344.  
  345.     if (!u) {
  346.         DEBUG(("uni_rename: old file not found"));
  347.         return EFILNF;
  348.     }
  349.  
  350. /* the new name is not allowed to exist! */
  351.     r = uni_lookup(newdir, newname, &fc);
  352.     if (r != EFILNF) {
  353.         DEBUG(("uni_rename: error %ld", r));
  354.         return (r == 0) ? EACCDN : r;
  355.     }
  356.  
  357.     (void)strncpy(u->name, newname, NAME_MAX);
  358.     return 0;
  359. }
  360.  
  361. static long ARGS_ON_STACK 
  362. uni_opendir(dirh, flags)
  363.     DIR *dirh;
  364.     int flags;
  365. {
  366.     UNUSED(flags);
  367.  
  368.     if (dirh->fc.index != 0) {
  369.         DEBUG(("uni_opendir: bad directory"));
  370.         return EPTHNF;
  371.     }
  372.     dirh->index = 0;
  373.     return 0;
  374. }
  375.  
  376.  
  377. static long ARGS_ON_STACK 
  378. uni_readdir(dirh, name, namelen, fc)
  379.     DIR *dirh;
  380.     char *name;
  381.     int namelen;
  382.     fcookie *fc;
  383. {
  384.     long map;
  385.     char *dirname;
  386.     int i;
  387.     int giveindex = (dirh->flags == 0);
  388.     UNIFILE *u;
  389.     long index;
  390.     extern long dosdrvs;
  391.     long r;
  392.  
  393.     map = dosdrvs | drvmap() | PSEUDODRVS;
  394.     i = dirh->index++;
  395.     u = u_root;
  396.     while (i > 0) {
  397.         --i;
  398.         u = u->next;
  399.         if (!u)
  400.             break;
  401.     }
  402. tryagain:
  403.     if (!u) return ENMFIL;
  404.  
  405.     dirname = u->name;
  406.     index = (long)u;
  407.     if ( (u->mode & S_IFMT) == S_IFDIR ) {
  408. /* make sure the drive really exists */
  409.         if ( u->dev >= NUM_DRIVES) {
  410.             r = (*u->fs->root)(u->dev,fc);
  411.             if (r) {
  412.             fc->fs = &uni_filesys;
  413.             fc->index = 0;
  414.             fc->dev = u->dev;
  415.             }
  416.         } else {
  417.             if ((map & (1L << u->dev)) == 0 ) {
  418.             dirh->index++;
  419.             u = u->next;
  420.             goto tryagain;
  421.             }
  422.             *fc = curproc->root[u->dev];
  423.             if (!fc->fs) {    /* drive not yet initialized */
  424.         /* use default attributes */
  425.             fc->fs = &uni_filesys;
  426.             fc->index = 0;
  427.             fc->dev = u->dev;
  428.             }
  429.         }
  430.     } else {        /* a symbolic link */
  431.         fc->fs = &uni_filesys;
  432.         fc->dev = UNIDRV;
  433.         fc->index = (long)u;
  434.     }
  435.  
  436.     if (giveindex) {
  437.         namelen -= (int)sizeof(long);
  438.         if (namelen <= 0) return ERANGE;
  439.         *((long *)name) = index;
  440.         name += sizeof(long);
  441.     }
  442.     strncpy(name, dirname, namelen-1);
  443.     if (strlen(name) < strlen(dirname))
  444.         return ENAMETOOLONG;
  445.     return 0;
  446. }
  447.  
  448. static long ARGS_ON_STACK 
  449. uni_rewinddir(dirh)
  450.     DIR *dirh;
  451. {
  452.     dirh->index = 0;
  453.     return 0;
  454. }
  455.  
  456. static long ARGS_ON_STACK 
  457. uni_closedir(dirh)
  458.     DIR *dirh;
  459. {
  460.     UNUSED(dirh);
  461.     return 0;
  462. }
  463.  
  464. static long ARGS_ON_STACK 
  465. uni_pathconf(dir, which)
  466.     fcookie *dir;
  467.     int which;
  468. {
  469.     UNUSED(dir);
  470.  
  471.     switch(which) {
  472.     case -1:
  473.         return DP_MAXREQ;
  474.     case DP_IOPEN:
  475.         return 0;        /* no files to open */
  476.     case DP_MAXLINKS:
  477.         return 1;        /* no hard links available */
  478.     case DP_PATHMAX:
  479.         return PATH_MAX;
  480.     case DP_NAMEMAX:
  481.         return NAME_MAX;
  482.     case DP_ATOMIC:
  483.         return 1;        /* no atomic writes */
  484.     case DP_TRUNC:
  485.         return DP_AUTOTRUNC;
  486.     case DP_CASE:
  487.         return DP_CASEINSENS;
  488.     default:
  489.         return EINVFN;
  490.     }
  491. }
  492.  
  493. static long ARGS_ON_STACK 
  494. uni_dfree(dir, buf)
  495.     fcookie *dir;
  496.     long *buf;
  497. {
  498.     UNUSED(dir);
  499.  
  500.     buf[0] = 0;    /* number of free clusters */
  501.     buf[1] = 0;    /* total number of clusters */
  502.     buf[2] = 1;    /* sector size (bytes) */
  503.     buf[3] = 1;    /* cluster size (sectors) */
  504.     return 0;
  505. }
  506.  
  507. static DEVDRV * ARGS_ON_STACK 
  508. uni_getdev(fc, devsp)
  509.     fcookie *fc;
  510.     long *devsp;
  511. {
  512.     UNUSED(fc);
  513.  
  514.     *devsp = EACCDN;
  515.     return 0;
  516. }
  517.  
  518. static long ARGS_ON_STACK 
  519. uni_symlink(dir, name, to)
  520.     fcookie *dir;
  521.     const char *name;
  522.     const char *to;
  523. {
  524.     UNIFILE *u;
  525.     fcookie fc;
  526.     long r;
  527.  
  528.     r = uni_lookup(dir, name, &fc);
  529.     if (r == 0) return EACCDN;    /* file already exists */
  530.     if (r != EFILNF) return r;    /* some other error */
  531.  
  532.     u = kmalloc(SIZEOF(UNIFILE));
  533.     if (!u) return EACCDN;
  534.  
  535.     strncpy(u->name, name, NAME_MAX);
  536.     u->name[NAME_MAX] = 0;
  537.  
  538.     u->data = kmalloc((long)strlen(to)+1);
  539.     if (!u->data) {
  540.         kfree(u);
  541.         return EACCDN;
  542.     }
  543.     strcpy(u->data, to);
  544.     u->mode = S_IFLNK | DEFAULT_DIRMODE;
  545.     u->dev = curproc->ruid;
  546.     u->next = u_root;
  547.     u->fs = &uni_filesys;
  548.     u_root = u;
  549.     return 0;
  550. }
  551.  
  552. static long ARGS_ON_STACK 
  553. uni_readlink(fc, buf, buflen)
  554.     fcookie *fc;
  555.     char *buf;
  556.     int buflen;
  557. {
  558.     UNIFILE *u;
  559.  
  560.     u = (UNIFILE *)fc->index;
  561.     assert(u);
  562.     assert((u->mode & S_IFMT) == S_IFLNK);
  563.     assert(u->data);
  564.     strncpy(buf, u->data, buflen);
  565.     if (strlen(u->data) >= buflen)
  566.         return ENAMETOOLONG;
  567.     return 0;
  568. }
  569.